home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / daemons / cron / RCS / cron.c,v < prev    next >
Encoding:
Text File  |  1991-04-12  |  16.2 KB  |  978 lines

  1. head     1.5;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    ; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.5
  10. date     90.02.16.12.54.50;  author douglis;  state Exp;
  11. branches 1.5.1.1;
  12. next     1.4;
  13.  
  14. 1.4
  15. date     89.09.11.12.48.21;  author douglis;  state Exp;
  16. branches ;
  17. next     1.3;
  18.  
  19. 1.3
  20. date     88.12.14.10.59.16;  author ouster;  state Exp;
  21. branches ;
  22. next     1.2;
  23.  
  24. 1.2
  25. date     88.03.31.17.19.21;  author deboor;  state Exp;
  26. branches ;
  27. next     1.1;
  28.  
  29. 1.1
  30. date     87.09.08.13.21.49;  author deboor;  state Exp;
  31. branches ;
  32. next     ;
  33.  
  34. 1.5.1.1
  35. date     91.04.12.13.17.12;  author rab;  state Exp;
  36. branches ;
  37. next     ;
  38.  
  39.  
  40. desc
  41. @daemon to run all the time and run other things occasionally
  42. @
  43.  
  44.  
  45. 1.5
  46. log
  47. @
  48. use hex pids
  49. @
  50. text
  51. @/* 
  52.  * cron.c --
  53.  *
  54.  *    Cron daemon.  Reads /hosts/{hostname}/crontab.  Wakes
  55.  *      up periodically to run the commands.
  56.  *
  57.  * Copyright 1989 Regents of the University of California
  58.  * Permission to use, copy, modify, and distribute this
  59.  * software and its documentation for any purpose and without
  60.  * fee is hereby granted, provided that the above copyright
  61.  * notice appear in all copies.  The University of California
  62.  * makes no representations about the suitability of this
  63.  * software for any purpose.  It is provided "as is" without
  64.  * express or implied warranty.
  65.  */
  66.  
  67. #ifndef lint
  68. static char rcsid[] = "$Header: /sprite/src/daemons/cron/RCS/cron.c,v 1.4 89/09/11 12:48:21 douglis Exp Locker: douglis $";
  69. #endif /* not lint */
  70.  
  71.  
  72. #include <sys/types.h>
  73. #include <stdio.h>
  74. #include <stdlib.h>
  75. #include <ctype.h>
  76. #include <signal.h>
  77. #include <sys/time.h>
  78. #include <sys/stat.h>
  79. #include <sys/wait.h>
  80. #include <sys/ioctl.h>
  81. #include <sys/file.h>
  82. #include <pwd.h>
  83. #include <fcntl.h>
  84.  
  85. #define    LISTS    (2*BUFSIZ)
  86. #define    MAXLIN    BUFSIZ
  87.  
  88. #ifndef CRONTAB
  89. #define CRONTAB "/sprite/lib/cron/crontab"
  90. #endif
  91.  
  92. #ifndef CRONTABLOC
  93. #define CRONTABLOC  "/usr/lib/crontab.local"
  94. #endif
  95.  
  96. #define    EXACT    100
  97. #define    ANY    101
  98. #define    LIST    102
  99. #define    RANGE    103
  100. #define    EOS    104
  101.  
  102. static char    crontab[]    = CRONTAB;
  103. static char    loc_crontab[256]   = CRONTABLOC;
  104. static time_t    itime;
  105. static struct    tm *loct;
  106. extern struct    tm *localtime();
  107. static int    flag;
  108. static char    *list;
  109. static char    *listend;
  110. static unsigned listsize;
  111.  
  112. static FILE    *debug;
  113. #define dprintf if (debug) fprintf
  114.  
  115. static char *cmp();
  116. static void slp();
  117. static void ex();
  118. static void init();
  119. static void append();
  120. static void reapchild();
  121. static void untty();
  122. static int number();
  123. static void Fs_GetPrivateName();
  124.  
  125. void
  126. main(argc, argv)
  127.     int argc;
  128.     char **argv;
  129. {
  130.     register char *cp;
  131.     char *cmp();
  132.     time_t filetime = 0;
  133.     time_t lfiletime = 0;
  134.     char c;
  135.     extern char *optarg;
  136.     extern int errno;
  137.  
  138.      /*
  139.       * Check command line arguments
  140.       */
  141.      c = getopt(argc, argv, "d:");
  142.      if (c == 'd') {
  143.      if ((debug = fopen(optarg, "w")) == NULL) {
  144.          fprintf(stderr, "Can't open %s: %s\n", optarg, strerror(errno));
  145.          exit(1);
  146.      }   
  147.      fcntl(fileno(debug), F_SETFL, FAPPEND);
  148.      }
  149.     /*
  150.      * Detach from parent.
  151.      */
  152.      if (!debug && fork()) {
  153.      exit(0);
  154.      }
  155.  
  156.      chdir("/");
  157.      freopen("/", "r", stdout);
  158.      freopen("/", "r", stderr);
  159.      untty();
  160.  
  161.      /*
  162.       * Ignore signals
  163.       */
  164.      signal(SIGHUP, SIG_IGN);
  165.      signal(SIGINT, SIG_IGN);
  166. #ifndef sprite
  167.      signal(SIGQUIT, SIG_IGN);
  168. #endif
  169.      signal(SIGCHLD, reapchild);
  170.      time(&itime);
  171.      itime -= localtime(&itime)->tm_sec;
  172.  
  173.      Fs_GetPrivateName("crontab", loc_crontab);
  174.  
  175.      for (;; itime+=60, slp()) {
  176.      struct stat cstat, lcstat;
  177.      int newcron, newloc;
  178.  
  179.      newcron = 0;
  180.      if (stat(crontab, &cstat) < 0) {
  181.          cstat.st_mtime = 1;
  182.      }   
  183.      if (cstat.st_mtime != filetime) {
  184.          filetime = cstat.st_mtime;
  185.          newcron++;
  186.      }
  187.      newloc  = 0;
  188.      if (stat(loc_crontab, &lcstat) < 0) {
  189.          lcstat.st_mtime = 1;
  190.      }
  191.      if (lcstat.st_mtime != lfiletime) {
  192.          lfiletime = lcstat.st_mtime;
  193.          newloc++;
  194.      }
  195.      if (newcron || newloc) {
  196.          dprintf(debug, "%x: reading crontab files\n", getpid()),
  197.              fflush(debug);
  198.          init();
  199.          append(crontab);
  200.          append(loc_crontab);
  201.          *listend++ = EOS;
  202.          *listend++ = EOS;
  203.      }
  204.      loct = localtime(&itime);
  205.      loct->tm_mon++;         /* 1-12 for month */
  206.      if (loct->tm_wday == 0) {
  207.          loct->tm_wday = 7;    /* sunday is 7, not 0 */
  208.      }
  209.      for(cp = list; *cp != EOS;) {
  210.          flag = 0;
  211.          cp = cmp(cp, loct->tm_min);
  212.          cp = cmp(cp, loct->tm_hour);
  213.          cp = cmp(cp, loct->tm_mday);
  214.          cp = cmp(cp, loct->tm_mon);
  215.          cp = cmp(cp, loct->tm_wday);
  216.          if(flag == 0) {
  217.          ex(cp);
  218.          }   
  219.          while(*cp++ != 0) {
  220.          ;
  221.          }
  222.      }
  223.      }   
  224. }
  225.  
  226. static char *
  227. cmp(p, v)
  228.     char *p;
  229. {
  230.     register char *cp;
  231.  
  232.     cp = p;
  233.     switch(*cp++) {
  234.  
  235.     case EXACT:
  236.     if (*cp++ != v) {
  237.         flag++;
  238.     }
  239.     return cp;
  240.  
  241.     case ANY:
  242.     return cp;
  243.  
  244.     case LIST:
  245.     while(*cp != LIST) {
  246.         if(*cp++ == v) {
  247.         while(*cp++ != LIST) {
  248.             ;
  249.         }
  250.         return cp;
  251.         }
  252.     }
  253.     flag++;
  254.     return cp+1;
  255.  
  256.     case RANGE:
  257.     if(*cp > v || cp[1] < v) {
  258.         flag++;
  259.     }
  260.     return cp+2;
  261.     }
  262.     if(cp[-1] != v) {
  263.     flag++;
  264.     }
  265.     return cp;
  266. }
  267.  
  268. static void
  269. slp()
  270. {
  271.     register i;
  272.     time_t t;
  273.  
  274.     time(&t);
  275.     i = itime - t;
  276.     if(i < -60 * 60 || i > 60 * 60) {
  277.     itime = t;
  278.     i = 60 - localtime(&itime)->tm_sec;
  279.     itime += i;
  280.     }
  281.     if(i > 0) {
  282.     sleep(i);
  283.     }
  284.     return;
  285. }
  286.  
  287. static void
  288. ex(s)
  289.     char *s;
  290. {
  291.     int st;
  292.     register struct passwd *pwd;
  293.     char user[BUFSIZ];
  294.     char *c = user;
  295.     int pid;
  296.  
  297.     if (fork()) {
  298.     return;
  299.     }
  300.  
  301.     pid = getpid();
  302.     while(*s != ' ' && *s != '\t') {
  303.     *c++ = *s++;
  304.     }
  305.     *c = '\0';
  306.     s++;
  307.     if ((pwd = getpwnam(user)) == NULL) {
  308.     dprintf(debug, "%x: cannot find %s\n", pid, user),
  309.         fflush(debug);
  310.         exit(1);
  311.     }   
  312.     (void) setgid(pwd->pw_gid);
  313.     initgroups(pwd->pw_name, pwd->pw_gid);
  314.     (void) setuid(pwd->pw_uid);
  315.     freopen("/", "r", stdin);
  316.     dprintf(debug, "%x: executing %s", pid, s), fflush (debug);
  317.     execl("/bin/sh", "sh", "-c", s, 0);
  318.     dprintf(debug, "%x: cannot execute sh\n", pid), fflush (debug);
  319.     exit(0);
  320. }
  321.  
  322. static void
  323. init()
  324. {
  325.     /*
  326.      * Don't free in case was longer than LISTS.  Trades off
  327.      * the rare case of crontab shrinking vs. the common case of
  328.      * extra realloc's needed in append() for a large crontab.
  329.      */
  330.     if (list == 0) {
  331.     list = malloc(LISTS);
  332.     listsize = LISTS;
  333.     }
  334.     listend = list;
  335.     return;
  336. }
  337.  
  338. static void
  339. append(fn)
  340.     char *fn;
  341. {
  342.     register i, c;
  343.     register char *cp;
  344.     register char *ocp;
  345.     register int n;
  346.  
  347.     if (freopen(fn, "r", stdin) == NULL) {
  348.     return;
  349.     }
  350.     cp = listend;
  351. loop:
  352.     if(cp > list+listsize-MAXLIN) {
  353.     int length = cp - list;
  354.  
  355.     listsize += LISTS;
  356.     list = realloc(list, listsize);
  357.     cp = list + length;
  358.     }
  359.     ocp = cp;
  360.     for(i=0;; i++) {
  361.     do {
  362.         c = getchar();
  363.     } while(c == ' ' || c == '\t');
  364.     if(c == EOF || c == '\n') {
  365.         goto ignore;
  366.     }
  367.     if(i == 5) {
  368.         break;
  369.     }
  370.     if(c == '*') {
  371.         *cp++ = ANY;
  372.         continue;
  373.     }
  374.     if ((n = number(c)) < 0) {
  375.         goto ignore;
  376.     }
  377.     c = getchar();
  378.     if(c == ',') {
  379.         goto mlist;
  380.     }
  381.     if(c == '-') {
  382.         goto mrange;
  383.     }
  384.     if(c != '\t' && c != ' ') {
  385.         goto ignore;
  386.     }
  387.     *cp++ = EXACT;
  388.     *cp++ = n;
  389.     continue;
  390.  
  391.     mlist:
  392.     *cp++ = LIST;
  393.     *cp++ = n;
  394.     do {
  395.         if ((n = number(getchar())) < 0) {
  396.         goto ignore;
  397.         }
  398.         *cp++ = n;
  399.         c = getchar();
  400.     } while (c==',');
  401.     if(c != '\t' && c != ' ') {
  402.         goto ignore;
  403.     }
  404.     *cp++ = LIST;
  405.     continue;
  406.  
  407.     mrange:
  408.     *cp++ = RANGE;
  409.     *cp++ = n;
  410.     if ((n = number(getchar())) < 0) {
  411.             goto ignore;
  412.     }
  413.     c = getchar();
  414.     if(c != '\t' && c != ' ') {
  415.         goto ignore;
  416.     }
  417.     *cp++ = n;
  418.     }
  419.     while(c != '\n') {
  420.     if(c == EOF) {
  421.         goto ignore;
  422.     }
  423.     if(c == '%') {
  424.         c = '\n';
  425.     }
  426.     *cp++ = c;
  427.     c = getchar();
  428.     }
  429.     *cp++ = '\n';
  430.     *cp++ = 0;
  431.     goto loop;
  432.  
  433. ignore:
  434.     cp = ocp;
  435.     while(c != '\n') {
  436.     if(c == EOF) {
  437.         fclose(stdin);
  438.         listend = cp;
  439.         return;
  440.     }
  441.     c = getchar();
  442.     }
  443.     goto loop;
  444. }
  445.  
  446. static int
  447. number(c)
  448.     register c;
  449. {
  450.     register n = 0;
  451.  
  452.     while (isdigit(c)) {
  453.     n = n*10 + c - '0';
  454.     c = getchar();
  455.     }
  456.     ungetc(c, stdin);
  457.     if (n>=100) {
  458.     return -1;
  459.     }
  460.     return n;
  461. }
  462.  
  463. static void
  464. reapchild()
  465. {
  466.     union wait status;
  467.     int pid;
  468.  
  469.     while ((pid = wait3(&status, WNOHANG, 0)) > 0) {
  470.     dprintf(debug, "%x: child exits with signal %d status %d\n",
  471.         pid, status.w_termsig, status.w_retcode),
  472.         fflush (debug);
  473.     }
  474.     return;
  475. }
  476.  
  477. static void
  478. untty()
  479. {
  480.     int i;
  481.  
  482.     i = open("/dev/tty", O_RDWR);
  483.     if (i >= 0) {
  484.     ioctl(i, TIOCNOTTY, (char *)0);
  485.     (void) close(i);
  486.     }
  487.     return;
  488. }
  489.  
  490.  
  491. /*
  492.  *----------------------------------------------------------------------
  493.  *
  494.  * Fs_GetPrivateName --
  495.  *
  496.  *      Fill a buffer with the path name of a file private to the local
  497.  *      machine. The file is located in /hosts/<hostname>/<file>
  498.  *
  499.  * Results:
  500.  *      The path of the file.
  501.  *
  502.  * Side Effects:
  503.  *      The passed buffer is overwritten.
  504.  *
  505.  *----------------------------------------------------------------------
  506.  */
  507. static void
  508. Fs_GetPrivateName (fileName, bufPtr)
  509.     char                *fileName;      /* Short name of private file */
  510.     char                *bufPtr;        /* Pointer to buffer for storage */
  511. {
  512.     static int          initialized = 0;
  513.     static char         hostname[64];   /* Name of local host */
  514.  
  515. #define PRIVATE_DIR     "/hosts"
  516.  
  517.     if (!initialized) {
  518.         gethostname (hostname, sizeof(hostname));
  519.     hostname[sizeof(hostname)-1] = 0;
  520.         initialized = 1;
  521.     }
  522.  
  523.     sprintf (bufPtr, "%s/%s/%s", PRIVATE_DIR, hostname, fileName);
  524.     return;
  525. }
  526. @
  527.  
  528.  
  529. 1.5.1.1
  530. log
  531. @Debugging changes (?) (Mike checking in for Bob.)
  532. @
  533. text
  534. @d18 1
  535. a18 1
  536. static char rcsid[] = "$Header: /sprite/src/daemons/cron/RCS/cron.c,v 1.5 90/02/16 12:54:50 douglis Exp Locker: rab $";
  537. a51 2
  538. extern int errno;
  539.  
  540. d86 1
  541. a231 1
  542.     dprintf(debug, "Sleeping for %d seconds\n", i);
  543. a475 1
  544.  
  545. @
  546.  
  547.  
  548. 1.4
  549. log
  550. @conversion to ANSI C?  (ci by FD for RAB)
  551. @
  552. text
  553. @d18 1
  554. a18 1
  555. static char rcsid[] = "$Header$";
  556. d39 1
  557. a39 1
  558. #define CRONTAB "/lib/crontab"
  559. a87 7
  560.     /*
  561.      * Detach from parent.
  562.      */
  563.      if (fork()) {
  564.      exit(0);
  565.      }
  566.  
  567. d99 7
  568. d116 1
  569. d118 1
  570. d146 2
  571. d258 1
  572. a258 1
  573.     dprintf(debug, "%d: cannot find %s\n", pid, user),
  574. d266 1
  575. a266 1
  576.     dprintf(debug, "%d: executing %s", pid, s), fflush (debug);
  577. d268 1
  578. a268 1
  579.     dprintf(debug, "%d: cannot execute sh\n", pid), fflush (debug);
  580. d420 1
  581. a420 1
  582.     dprintf(debug, "%d: child exits with signal %d status %d\n",
  583. @
  584.  
  585.  
  586. 1.3
  587. log
  588. @Eliminate ancient Sprite library calls.
  589. @
  590. text
  591. @d1 16
  592. d18 3
  593. a20 2
  594. static char *sccsid = "@@(#)cron.c    4.12 (Berkeley) 5/27/86";
  595. #endif
  596. d24 1
  597. d52 9
  598. a60 13
  599. char    crontab[]    = CRONTAB;
  600. char    loc_crontab[256]   = CRONTABLOC;
  601. time_t    itime;
  602. struct    tm *loct;
  603. struct    tm *localtime();
  604. char    *malloc();
  605. char    *realloc();
  606. int    reapchild();
  607. void    Fs_GetPrivateName();
  608. int    flag;
  609. char    *list;
  610. char    *listend;
  611. unsigned listsize;
  612. d62 1
  613. a62 1
  614. FILE    *debug;
  615. d65 11
  616. d80 90
  617. a169 74
  618.     register char *cp;
  619.     char *cmp();
  620.     time_t filetime = 0;
  621.     time_t lfiletime = 0;
  622.     char c;
  623.     extern char *optarg;
  624.  
  625.     if (fork())
  626.         exit(0);
  627.     c = getopt(argc, argv, "d:");
  628.     if (c == 'd') {
  629.         debug = fopen(optarg, "w");
  630.         if (debug == NULL)
  631.             exit(1);
  632.         fcntl(fileno(debug), F_SETFL, FAPPEND);
  633.     }
  634.     chdir("/");
  635.     freopen("/", "r", stdout);
  636.     freopen("/", "r", stderr);
  637.     untty();
  638.     signal(SIGHUP, SIG_IGN);
  639.     signal(SIGINT, SIG_IGN);
  640.     signal(SIGQUIT, SIG_IGN);
  641.     signal(SIGCHLD, reapchild);
  642.     time(&itime);
  643.     itime -= localtime(&itime)->tm_sec;
  644.  
  645.     Fs_GetPrivateName("crontab", loc_crontab);
  646.  
  647.     for (;; itime+=60, slp()) {
  648.         struct stat cstat, lcstat;
  649.         int newcron, newloc;
  650.         
  651.         newcron = 0;
  652.         if (stat(crontab, &cstat) < 0)
  653.             cstat.st_mtime = 1;
  654.         if (cstat.st_mtime != filetime) {
  655.             filetime = cstat.st_mtime;
  656.             newcron++;
  657.         }
  658.  
  659.         newloc  = 0;
  660.         if (stat(loc_crontab, &lcstat) < 0)
  661.             lcstat.st_mtime = 1;
  662.         if (lcstat.st_mtime != lfiletime) {
  663.             lfiletime = lcstat.st_mtime;
  664.             newloc++;
  665.         }
  666.  
  667.         if (newcron || newloc) {
  668.             init();
  669.             append(crontab);
  670.             append(loc_crontab);
  671.             *listend++ = EOS;
  672.             *listend++ = EOS;
  673.         }
  674.  
  675.         loct = localtime(&itime);
  676.         loct->tm_mon++;         /* 1-12 for month */
  677.         if (loct->tm_wday == 0)
  678.             loct->tm_wday = 7;    /* sunday is 7, not 0 */
  679.         for(cp = list; *cp != EOS;) {
  680.             flag = 0;
  681.             cp = cmp(cp, loct->tm_min);
  682.             cp = cmp(cp, loct->tm_hour);
  683.             cp = cmp(cp, loct->tm_mday);
  684.             cp = cmp(cp, loct->tm_mon);
  685.             cp = cmp(cp, loct->tm_wday);
  686.             if(flag == 0)
  687.                 ex(cp);
  688.             while(*cp++ != 0)
  689.                 ;
  690.         }
  691.     }
  692. d172 1
  693. a172 1
  694. char *
  695. d174 1
  696. a174 1
  697. char *p;
  698. d176 1
  699. a176 1
  700.     register char *cp;
  701. d178 34
  702. a211 29
  703.     cp = p;
  704.     switch(*cp++) {
  705.  
  706.     case EXACT:
  707.         if (*cp++ != v)
  708.             flag++;
  709.         return(cp);
  710.  
  711.     case ANY:
  712.         return(cp);
  713.  
  714.     case LIST:
  715.         while(*cp != LIST)
  716.             if(*cp++ == v) {
  717.                 while(*cp++ != LIST)
  718.                     ;
  719.                 return(cp);
  720.             }
  721.         flag++;
  722.         return(cp+1);
  723.  
  724.     case RANGE:
  725.         if(*cp > v || cp[1] < v)
  726.             flag++;
  727.         return(cp+2);
  728.     }
  729.     if(cp[-1] != v)
  730.         flag++;
  731.     return(cp);
  732. d214 1
  733. d217 2
  734. a218 2
  735.     register i;
  736.     time_t t;
  737. d220 11
  738. a230 9
  739.     time(&t);
  740.     i = itime - t;
  741.     if(i < -60 * 60 || i > 60 * 60) {
  742.         itime = t;
  743.         i = 60 - localtime(&itime)->tm_sec;
  744.         itime += i;
  745.     }
  746.     if(i > 0)
  747.         sleep(i);
  748. d233 1
  749. d235 1
  750. a235 1
  751. char *s;
  752. d237 29
  753. a265 28
  754.     int st;
  755.     register struct passwd *pwd;
  756.     char user[BUFSIZ];
  757.     char *c = user;
  758.     int pid;
  759.  
  760.     if (fork()) {
  761.         return;
  762.     }
  763.  
  764.     pid = getpid();
  765.     while(*s != ' ' && *s != '\t')
  766.         *c++ = *s++;
  767.     *c = '\0';
  768.     s++;
  769.     if ((pwd = getpwnam(user)) == NULL) {
  770.         dprintf(debug, "%d: cannot find %s\n", pid, user),
  771.             fflush(debug);
  772.         exit(1);
  773.     }
  774.     (void) setgid(pwd->pw_gid);
  775.     initgroups(pwd->pw_name, pwd->pw_gid);
  776.     (void) setuid(pwd->pw_uid);
  777.     freopen("/", "r", stdin);
  778.     dprintf(debug, "%d: executing %s", pid, s), fflush (debug);
  779.     execl("/bin/sh", "sh", "-c", s, 0);
  780.     dprintf(debug, "%d: cannot execute sh\n", pid), fflush (debug);
  781.     exit(0);
  782. d268 1
  783. d271 11
  784. a281 10
  785.     /*
  786.      * Don't free in case was longer than LISTS.  Trades off
  787.      * the rare case of crontab shrinking vs. the common case of
  788.      * extra realloc's needed in append() for a large crontab.
  789.      */
  790.     if (list == 0) {
  791.         list = malloc(LISTS);
  792.         listsize = LISTS;
  793.     }
  794.     listend = list;
  795. d284 1
  796. d286 1
  797. a286 1
  798. char *fn;
  799. d288 4
  800. a291 4
  801.     register i, c;
  802.     register char *cp;
  803.     register char *ocp;
  804.     register int n;
  805. d293 4
  806. a296 3
  807.     if (freopen(fn, "r", stdin) == NULL)
  808.         return;
  809.     cp = listend;
  810. d298 2
  811. a299 2
  812.     if(cp > list+listsize-MAXLIN) {
  813.         int length = cp - list;
  814. d301 67
  815. a367 54
  816.         listsize += LISTS;
  817.         list = realloc(list, listsize);
  818.         cp = list + length;
  819.     }
  820.     ocp = cp;
  821.     for(i=0;; i++) {
  822.         do
  823.             c = getchar();
  824.         while(c == ' ' || c == '\t')
  825.             ;
  826.         if(c == EOF || c == '\n')
  827.             goto ignore;
  828.         if(i == 5)
  829.             break;
  830.         if(c == '*') {
  831.             *cp++ = ANY;
  832.             continue;
  833.         }
  834.         if ((n = number(c)) < 0)
  835.             goto ignore;
  836.         c = getchar();
  837.         if(c == ',')
  838.             goto mlist;
  839.         if(c == '-')
  840.             goto mrange;
  841.         if(c != '\t' && c != ' ')
  842.             goto ignore;
  843.         *cp++ = EXACT;
  844.         *cp++ = n;
  845.         continue;
  846.  
  847.     mlist:
  848.         *cp++ = LIST;
  849.         *cp++ = n;
  850.         do {
  851.             if ((n = number(getchar())) < 0)
  852.                 goto ignore;
  853.             *cp++ = n;
  854.             c = getchar();
  855.         } while (c==',');
  856.         if(c != '\t' && c != ' ')
  857.             goto ignore;
  858.         *cp++ = LIST;
  859.         continue;
  860.  
  861.     mrange:
  862.         *cp++ = RANGE;
  863.         *cp++ = n;
  864.         if ((n = number(getchar())) < 0)
  865.             goto ignore;
  866.         c = getchar();
  867.         if(c != '\t' && c != ' ')
  868.             goto ignore;
  869.         *cp++ = n;
  870. d369 2
  871. a370 7
  872.     while(c != '\n') {
  873.         if(c == EOF)
  874.             goto ignore;
  875.         if(c == '%')
  876.             c = '\n';
  877.         *cp++ = c;
  878.         c = getchar();
  879. d372 6
  880. a377 3
  881.     *cp++ = '\n';
  882.     *cp++ = 0;
  883.     goto loop;
  884. d380 6
  885. a385 8
  886.     cp = ocp;
  887.     while(c != '\n') {
  888.         if(c == EOF) {
  889.             fclose(stdin);
  890.             listend = cp;
  891.             return;
  892.         }
  893.         c = getchar();
  894. d387 3
  895. a389 1
  896.     goto loop;
  897. d392 1
  898. d394 1
  899. a394 1
  900. register c;
  901. d396 1
  902. a396 1
  903.     register n = 0;
  904. d398 9
  905. a406 8
  906.     while (isdigit(c)) {
  907.         n = n*10 + c - '0';
  908.         c = getchar();
  909.     }
  910.     ungetc(c, stdin);
  911.     if (n>=100)
  912.         return(-1);
  913.     return(n);
  914. d409 1
  915. d412 2
  916. a413 2
  917.     union wait status;
  918.     int pid;
  919. d415 6
  920. a420 4
  921.     while ((pid = wait3(&status, WNOHANG, 0)) > 0)
  922.         dprintf(debug, "%d: child exits with signal %d status %d\n",
  923.             pid, status.w_termsig, status.w_retcode),
  924.             fflush (debug);
  925. d423 1
  926. d426 1
  927. a426 1
  928.     int i;
  929. d428 6
  930. a433 5
  931.     i = open("/dev/tty", O_RDWR);
  932.     if (i >= 0) {
  933.         ioctl(i, TIOCNOTTY, (char *)0);
  934.         (void) close(i);
  935.     }
  936. d435 1
  937. d453 1
  938. a453 1
  939. void
  940. d470 1
  941. @
  942.  
  943.  
  944. 1.2
  945. log
  946. @Added Fs_GetPrivateName to get host-specific file
  947. @
  948. text
  949. @d362 1
  950. a362 1
  951. #ifndef notdef
  952. d390 2
  953. a391 1
  954.         Sys_GetHostName (sizeof(hostname), hostname);
  955. d395 1
  956. a395 1
  957.     Io_PrintString (bufPtr, "%s/%s/%s", PRIVATE_DIR, hostname, fileName);
  958. a396 1
  959. #endif notdef
  960. @
  961.  
  962.  
  963. 1.1
  964. log
  965. @Initial revision
  966. @
  967. text
  968. @d21 1
  969. a21 1
  970. #define CRONTAB "/usr/lib/crontab"
  971. d35 1
  972. a35 1
  973. char    loc_crontab[]   = CRONTABLOC;
  974. d42 1
  975. d82 2
  976. d362 35
  977. @
  978.